package com.weilele.mvvm.base

import androidx.lifecycle.*
import com.weilele.mvvm.base.livedata.*
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext


/**
 * 描述：mvvm--基类ViewModel
 * 尽可能以函数为主，处理UI的逻辑操作
 */
open class MvvmViewModel : ViewModel() {
    private val liveDatas by lazy { hashMapOf<String, MutableLiveData<StatusData<Any?>>>() }

    /**
     * 存储Model
     */
    val modelList = mutableListOf<MvvmModel>()

    /**
     * 创建Model
     */
    inline fun <reified T : MvvmModel> getModel(): T {
        for (mvvmModel in modelList) {
            if (mvvmModel is T) {
                return mvvmModel
            }
        }
        val instance = T::class.java.newInstance()
        modelList.add(instance)
        return instance
    }

    /**
     * 创建Model
     */
    fun createModel(cls: Class<*>): Any {
        for (mvvmModel in modelList) {
            if (mvvmModel.javaClass.simpleName == cls.simpleName) {
                return mvvmModel
            }
        }
        val instance = cls.newInstance()
        modelList.add(instance as MvvmModel)
        return instance
    }

    /**
     * 默认在主线程启用一个协程
     */
    fun <T> MutableLiveData<StatusData<T>>.runInCoroutineScope(
        context: CoroutineContext = Dispatchers.Main,
        start: CoroutineStart = CoroutineStart.DEFAULT,
        resultCall: LiveDataRunnable = DefaultLiveDataRunnable,
        isToastError: Boolean = true/*是否toast出错误*/,
        runIfSuccess: Boolean = false/*当data处于success状态，是否仍然请求数据*/,
        errorCall: ((Throwable) -> T?)? = null,
        call: suspend CoroutineScope.() -> T?
    ): Job? {
        //region 如果值是success状态，则不再重新请求数据
        if (!runIfSuccess && this.isSuccess) {
            return null
        }
        //endregion
        return viewModelScope.launch(context, start) {
            resultCall.invoke(this@runInCoroutineScope, isToastError, errorCall) {
                call.invoke(this)
            }
        }
    }

    /**
     * 通过key创建livedata
     */
    fun <T> getLiveData(key: String): MutableLiveData<StatusData<T>> {
        val oldData = liveDatas[key]
        return if (oldData == null) {
            val newData = createStatusLiveData<Any?>()
            liveDatas[key] = newData
            newData as MutableLiveData<StatusData<T>>
        } else {
            oldData as MutableLiveData<StatusData<T>>
        }
    }

    /**
     * 做一写清理操作
     */
    override fun onCleared() {
        modelList.forEach {
            it.onCleared()
        }
        modelList.clear()
        super.onCleared()
    }
}